package tool;

import lombok.SneakyThrows;
import org.junit.Test;
import org.springframework.security.jwt.codec.Codecs;

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

/**
 * 解码器
 *
 * @author LiKe
 * @version 1.0.0
 * @date 2020-07-21 16:46
 */
//@SpringBootTest(classes = TokenCustomizeAuthorizationServer.class)
//@RunWith(SpringRunner.class)
public class Decoder {

    private static final String ALGORITHM = "RSA";

    private static final String RSA_PUBLIC_KEY =
            "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAlLx5bz3zu/ptZpVuvCBQZ4dMeDhmZJmyxia7A9706B5o/ipLFcZnjOtKVQcZTa8UOniTDJ46DmMyK2Q5oW8d24cpMdPSwxNMU/7dOv40DFnoFUFIWUR/+fAZVTCfJb7pBpzWpmLmvOhLV8rSOKbJTIeRUWgsFZsCJJaqIa3/6k7moTV4DURUgh1ABmMyXUd3/zeSkdPJXu9QCdxFygSPVJs4d5Bqr97mROIdt9qmngap1Lch2elwrzWuQx63mGxoK+lxEQB6ftdPLvpEABuCBs7hO18CBj5ei9G+foaFe/77muNCILAtvc8UiD6PRbf5e1YXEp0IHZisuOhedjqBFQIDAQAB";

    private static final String RSA_PRIVATE_KEY =
            "MIIDbzCCAlegAwIBAgIEAfMOsjANBgkqhkiG9w0BAQsFADBoMQswCQYDVQQGEwJDTjEQMA4GA1UECBMHU2ljaHVhbjEQMA4GA1UEBxMHQ2hlbmdkdTEQMA4GA1UEChMHY2FwbGlrZTERMA8GA1UECxMIcGVyc29uYWwxEDAOBgNVBAMTB2NhcGxpa2UwHhcNMjAwNzE3MDc0MzU0WhcNMzAwNzE1MDc0MzU0WjBoMQswCQYDVQQGEwJDTjEQMA4GA1UECBMHU2ljaHVhbjEQMA4GA1UEBxMHQ2hlbmdkdTEQMA4GA1UEChMHY2FwbGlrZTERMA8GA1UECxMIcGVyc29uYWwxEDAOBgNVBAMTB2NhcGxpa2UwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCUvHlvPfO7+m1mlW68IFBnh0x4OGZkmbLGJrsD3vToHmj+KksVxmeM60pVBxlNrxQ6eJMMnjoOYzIrZDmhbx3bhykx09LDE0xT/t06/jQMWegVQUhZRH/58BlVMJ8lvukGnNamYua86EtXytI4pslMh5FRaCwVmwIklqohrf/qTuahNXgNRFSCHUAGYzJdR3f/N5KR08le71AJ3EXKBI9Umzh3kGqv3uZE4h232qaeBqnUtyHZ6XCvNa5DHreYbGgr6XERAHp+108u+kQAG4IGzuE7XwIGPl6L0b5+hoV7/vua40IgsC29zxSIPo9Ft/l7VhcSnQgdmKy46F52OoEVAgMBAAGjITAfMB0GA1UdDgQWBBRqowFVjNkW77ZciS10KyMWs/3n2jANBgkqhkiG9w0BAQsFAAOCAQEAJ+d+/0ss/Hl8IhPuIbH5Hh3MMxK8f02/QBPyJ5+ZJgt9k1BZc6/eMYbWd41z05gb2m2arXfAS2HEdsY1pCfcssb85cVYUwMoDfK7pLRX34V0uhdUm0wqTBumIs2iCCLCz7Eci4XpAv+RWHVKXbg+pP7GrKBh0iNYTuV+pDr+D7K6rZwGjYsGAqqpc1LjNNaN68pHhTnwXu4igM/gLsNRmR+2zXyJ1FZegnk0fsFWojOqHwCZxYli9245N4HgePIVTvFTu+QzdLzFUcsGqhrynHfwQOvTyPMpaowpOsguNSzTdmRRK3QdtKHglE10us40NUJZQgavCigGcVwAv/jCdA==";

    @SneakyThrows
    @Test
    public void rsaDecoder() {
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(RSA_PUBLIC_KEY));
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, keyFactory.generatePublic(x509EncodedKeySpec));
        byte[] result = cipher.doFinal("XHTbHaZnpudapYmKxx2RDwiaV71h0GvG61Dtgbc5VYTPN3xBoA1n6Ws8uSHd0tUFM-dpbqDOzL4RUNrXs-baTwVpTvBxtjNUdRh0fp3Vc3aMnWxkyQVivDVU_ZbDTSoqUrsJOBanNYH-V89jWP1H-V5bNUQK2EWWnz6xVWRHIcAMUJhW8ZC-rekcVk-v5wA4CJH9XFvkNbOsGOLIUYNVXGY27LhlGKWuXf1_EX-6kTMp7fKFwBlrjuujBn2NpRvzKxTyfW5O8czG-7hPDCumpfOlrTYlCOzTXc5Xr7hNUMZYfIurV6WtU5A__-nvQYRt3HLO48OXlsgAWn7e8NfrCg".getBytes());
        System.out.println(Base64.getEncoder().encodeToString(result));
    }

    @SneakyThrows
    @Test
    public void verify() {
        final Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initVerify(composePublicKey());
        signature.update(
                Codecs.concat(
                        Codecs.b64UrlEncode("{\"alg\":\"RS256\",\"typ\":\"JWT\"}".getBytes()),
                        Codecs.utf8Encode("."),
                        Codecs.b64UrlEncode("{\"aud\":[\"resource-server\"],\"exp\":1595361118,\"user_name\":\"caplike\",\"jti\":\"ddfa1180-1400-4040-b657-0312f1d58b07\",\"client_id\":\"client-a\",\"scope\":[\"ACCESS_RESOURCE\"]}".getBytes())
                )
        );

        final byte[] crypto = "XHTbHaZnpudapYmKxx2RDwiaV71h0GvG61Dtgbc5VYTPN3xBoA1n6Ws8uSHd0tUFM-dpbqDOzL4RUNrXs-baTwVpTvBxtjNUdRh0fp3Vc3aMnWxkyQVivDVU_ZbDTSoqUrsJOBanNYH-V89jWP1H-V5bNUQK2EWWnz6xVWRHIcAMUJhW8ZC-rekcVk-v5wA4CJH9XFvkNbOsGOLIUYNVXGY27LhlGKWuXf1_EX-6kTMp7fKFwBlrjuujBn2NpRvzKxTyfW5O8czG-7hPDCumpfOlrTYlCOzTXc5Xr7hNUMZYfIurV6WtU5A__-nvQYRt3HLO48OXlsgAWn7e8NfrCg".getBytes();
        if (signature.verify(crypto)) {
            System.out.println(":: 验证　通过!");
        } else {
            System.err.println(":: 验证不通过!");
        }
    }

    @SneakyThrows
    @Test
    public void sign() {
        final Signature signature = Signature.getInstance("SHA256withRSA");
        signature.initSign(composePrivateKey());
        signature.update(
                Codecs.concat(
                        Codecs.b64UrlEncode("{\"alg\":\"RS256\",\"typ\":\"JWT\"}".getBytes()),
                        Codecs.utf8Encode("."),
                        Codecs.b64UrlEncode(Codecs.utf8Encode("{\"aud\":[\"resource-server\"],\"exp\":1595361118,\"user_name\":\"caplike\",\"jti\":\"ddfa1180-1400-4040-b657-0312f1d58b07\",\"client_id\":\"client-a\",\"scope\":[\"ACCESS_RESOURCE\"]}"))
                )
        );
        System.out.println(new String(signature.sign()));
    }

    private PublicKey composePublicKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(Base64.getDecoder().decode(RSA_PUBLIC_KEY));
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return keyFactory.generatePublic(x509EncodedKeySpec);
    }

    private PrivateKey composePrivateKey() throws NoSuchAlgorithmException, InvalidKeySpecException {
        PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(Base64.getDecoder().decode(RSA_PRIVATE_KEY));
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        return keyFactory.generatePrivate(pkcs8EncodedKeySpec);
    }
}
